package ftpcombiner;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.ParameterException;
import ftpcombiner.arguments.CommandArguments;
import ftpcombiner.backup.BackupThread;
import ftpcombiner.filesystem.FileSystem;
import ftpcombiner.gui.ApplicationFrame;
import ftpcombiner.gui.GUIResources;
import ftpcombiner.gui.SplashScreen;
import ftpcombiner.logger.Logger;
import ftpcombiner.properties.ApplicationProperties;
import java.io.FileNotFoundException;
import javax.swing.SwingUtilities;

/**
 *
 * @author Ben
 */
public class ApplicationController {

    private ApplicationFrame applicationFrame;
    private static ApplicationController instance = null;
    private ApplicationProperties applicationProperties;
    private static boolean loaded = false;
    private static CommandArguments arguments = new CommandArguments();
    private static SplashScreen splashScreen;

    public static ApplicationController getInstance() {
        if (instance == null) {
            instance = new ApplicationController();
            instance.loadGUI();
        }
        return instance;
    }

    public static ApplicationController getInstance(String[] args) {
        if (instance == null && !loaded) {
            instance = new ApplicationController();
            try {
                new JCommander(arguments, args);
            } catch (ParameterException e) {
                System.out.println(e.getMessage());
            }
            if (arguments.backup) {
                System.out.println("Entering backup mode...");
                try {
                    BackupThread.backup(arguments.backupConfigFile.get(0));
                } catch (FileNotFoundException ex) {
                    System.err.println("Cannot locate config file.");
                }
            } else {
                instance.loadGUI();
            }

        }
        return instance;
    }

    private ApplicationController() {
        //Logger.setUpLogging();
        System.out.println(Version.getPrettyString());
        //System.out.println("New Version");
        splashScreen = new SplashScreen();
        applicationProperties = new ApplicationProperties(GUIResources.getInstance().getPropertiesFile());

    }

    private void loadGUI() {
        if (!loaded) {
            loaded = true;

            FileSystem.getInstance();
            System.out.println("Loading GUI...");
            applicationFrame = new ApplicationFrame();

            System.out.println("Finished loading GUI");
            //getSplashScreen().incrementProgress();
            splashScreen.dispose();
            splashScreen = null;
        }
    }

    public ApplicationProperties getApplicationProperties() {
        return applicationProperties;
    }

    public ApplicationFrame getApplicationFrame() {
        return applicationFrame;
    }

    /**
     * The method that should be called when the app exits.
     */
    public void runOnExit() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                getApplicationProperties().save();
                FileSystem.getInstance().disconnect();
                Logger.close();
                System.exit(0);
            }
        });

    }

    public static SplashScreen getSplashScreen() {
        if (splashScreen != null) {
            return splashScreen;
        } else {
            throw new UnsupportedOperationException("Splash screen has been disposed or not yet created.");
        }
    }

    /**
     * Sets the status string in the status bar at the bottom of the
     * {@link ApplicationFrame}. This method is usually called instead using
     * {@link ApplicationController#setAppStatus(java.lang.String)} for
     * convenience. Note: When persist is used, make sure to manually turn off
     * persist when the status is no longer relevant.
     *
     * @param status The string to set that should be used in the status bar
     * @param persist Whether the status should remain in place until it is
     * overwritten or timeout after 6s
     *
     * @see StatusBar#setStatus(java.lang.String, boolean)
     * @see ApplicationController#setAppStatus(java.lang.String)
     */
    public synchronized void setAppStatus(String status, boolean persist) {
        applicationFrame.getStatusBar().setStatus(status, persist);
    }

    public void setAppStatus(String status) {
        applicationFrame.getStatusBar().setStatus(status, false);
    }

    /**
     * The class that holds the application version number and associated
     * methods.
     */
    public static class Version {

        public static final int[] VERSION_NUMBER = {0, 9, 6};
        public static final boolean IS_STABLE = false;

        /**
         * Gets the version of the application in a pretty printed string.
         *
         * @return A string that contains all the information about the version
         * of the application.
         * @see Version#getPrettyVersionNumber()
         */
        public static String getPrettyString() {
            return (IS_STABLE ? "Stable " : "Test ") + "Version " + getPrettyVersionNumber();
        }

        /**
         * Gets the version number of the application in the form of x.y.z
         *
         * @return The version number if the application.
         */
        public static String getPrettyVersionNumber() {
            return VERSION_NUMBER[0] + "." + VERSION_NUMBER[1] + "." + VERSION_NUMBER[2];
        }
    }

    public boolean isBackupMode() {
        return arguments.backup;
    }
}
